# 命名空间分类
# 每个函数都有着自已的命名空间，叫做局部命名空间，它记录了函数的变量，包括函数的参数和局部定义的变量
# 每个模块拥有它自已的命名空间，叫做全局命名空间，它记录了模块的变量，包括函数、类、其它导入的模块、模块级的变量和常量
# 内置命名空间，任何模块均可访问它，它存放着内置的函数和异常

# 命名空间查找规则
# 局部命名空间：特指当前函数或类的方法，如果函数定义了一个局部变量 x，或一个参数x，Python 将使用它，然后停止搜索
# 全局命名空间：特指当前的模块，如果模块定义了一个名为 x 的变量、函数或类，Python将使用它然后停止搜索
# 内置命名空间：对每个模块都是全局的，作为最后的尝试，Python 将假设 x 是内置函数或变量
# 如果 Python 在这些命名空间找不到 x，它将放弃查找并引发一个 NameError 异常，如 NameError: name 'xxx' is not defined

# 当函数嵌套时的查找规则
# 先在当前 (嵌套的或 lambda) 函数的命名空间中搜索
# 然后是在父函数的命名空间中搜索
# 接着是模块命名空间中搜索
# 最后在内置命名空间中搜索

# msg = "msg"


# def my_func():
#     name = "小北 "
#
#     def func_son():
#         name = "小南 "  # 此处的name变量，覆盖了父函数的name变量
#         print(name)
#
#     # 调用内部函数
#     func_son()
#     print(name)
#
#
# my_func()


# 命名空间的生命周期
# 内置命名空间在 Python 解释器启动时创建，会一直保留，不被删除
# 模块的全局命名空间在模块定义被读入时创建，通常模块命名空间也会一直保存到解释器退出
# 当函数被调用时创建一个局部命名空间，当函数返回结果或抛出异常时，被删除，每一个递归调用的函数都拥有自己的命名空间
# a = 1
#
#
# def my_func(str):
#     global a
#     if a == 1:
#         print(str)
#         a = 24
#
#
# my_func("file")
# print(a)

# 命名空间的访问
# 局部命名空间的访问
# def my_func():
#     a = 1
#     b = 2
#     print(locals())
#
#
# my_func()

# 全局命名空间的访问
# a = 1
# b = 2
#
# print(globals())


# locals 与 globals 之间的区别
# locals 是只读的，但 globals 是可读写的

# def my_func():
#     x = 123
#     print(locals())
#     locals()["x"] = 456
#     print("x=", x)
#
#
# y = 123
# my_func()
# globals()["y"] = 111
# print("y=", y)

a = 2
